home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / eulisp / mpfeel.lha / MPFeel / Modules / elopt.em < prev    next >
Lisp/Scheme  |  1992-10-06  |  11KB  |  314 lines

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                           ;;
  3. ;;  EuLisp Module                     Copyright (C) University of Bath 1991  ;;
  4. ;;                                                                           ;;
  5. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  6.  
  7. ; $Id:$
  8. ;
  9. ; $Log:$
  10.  
  11. (defmodule elopt
  12.  
  13.   (standard
  14.    loops
  15.    trandecl
  16.    tranutil) ()
  17.  
  18.   (deflocal ModuleName)
  19.   (deflocal bblist)
  20.   (deflocal endsbb-table (make-table))
  21.   (deflocal instr-type-table (make-table))
  22.   (deflocal opt-code-stream)
  23.   (deflocal label-tab)
  24.   (deflocal def-use-table)
  25.  
  26.   (defstruct opt-basic-block ()
  27.     (
  28.      ;; first-ins is the list on instructions which make up the basic block
  29.      ;; last-ins is the last instruction in the basic block
  30.      ;; next-blk is a list of basic blocks which may follow this one (max 2)
  31.      ;; prev-blk is a list of basic block which may preceed this one
  32.      (first-ins initform nil initarg first-ins accessor first-ins)
  33.      (last-ins initform nil initarg last-ins accessor last-ins)
  34.      (next-blk initform nil initarg next-blk accessor next-blk)
  35.      (prev-blk initform nil initarg prev-blk accessor prev-blk)
  36.      (gen initform nil initarg gen accessor gen)
  37.      (kill initform nil initarg kill accessor kill)
  38.      )
  39.     constructor make-opt-basic-block)
  40.   
  41.   (defmethod generic-prin ((x opt-basic-block) s)
  42.     (format s "#<opt-basic-block:~u~%" x)
  43.     (format s "~tfirst: ~a last:~a~%" (first-ins x) (last-ins x))
  44.     (for (setq i (next-blk x)) i (setq i (cdr i))
  45.      (format s "~t~tnext ~u" (car i)))
  46.     (format s "~%")
  47.     (for (setq i (prev-blk x)) i (setq i (cdr i))
  48.      (format s "~t~tprev ~u" (car i)))
  49.     (format s "~%gen:  ~a~%" (gen x))
  50.     (format s "kill: ~a>~%" (kill x)))
  51.  
  52.   (defmethod generic-write ((x opt-basic-block) s)
  53.     (format s "#<opt-basic-block:~u~%" x)
  54.     (format s "~tfirst: ~a last:~a~%" (first-ins x) (last-ins x))
  55.     (for (setq i (next-blk x)) i (setq i (cdr i))
  56.      (format s "~t~tnext ~u" (car i)))
  57.     (format s "~%")
  58.     (for (setq i (prev-blk x)) i (setq i (cdr i))
  59.      (format s "~t~tprev ~u" (car i)))
  60.     (format s "~%gen:  ~a~%" (gen x))
  61.     (format s "kill: ~a>~%" (kill x)))
  62.     
  63.  
  64.   (defcondition elopt-error ())
  65.  
  66.   (defun fourth (x) (car (cdr (cdr (cdr x)))))
  67.   (defun third (x) (car (cdr (cdr x))))
  68.   (defun second (x) (cadr x))
  69.   (defun first (x) (car x))
  70.  
  71.   (defun table-ref-or-bust (table slot)
  72.     (let ((x (table-ref table slot)))
  73.       (if x x
  74.     (error "table-ref-or-bust failed to find a value" elopt-error))))
  75.   
  76.   (defun optimise (a)
  77.     (opt-aux (copy-list a)))
  78.   
  79.   (defun opt-aux (a)
  80.     (let ((args (code-list a)))
  81.       (if (eq (caar args) 'entry)
  82.           (opt-entry a)
  83.       (error "Does not look like a command" elopt-error))
  84.       (mapc opt-aux (enclosed-blocks a))))
  85.  
  86. ;;; OK, given something which looks like
  87. ;;; ((entry name nargs results) (load...) (store...) (...) (...) (...))
  88. ;;; we split it up into a list of basic blocks                    
  89.   (defun opt-entry1 (block)
  90.     (cond ((null block) nil)
  91.       ((table-ref endsbb-table (caar block))
  92.        (let* ((temp (cdr block))    ; hold the list after the cut
  93.           (current-bb (make-opt-basic-block 'first-ins temp)))
  94.          (setf (last-ins (car bblist)) (car block))
  95.          (setq bblist (cons current-bb bblist))
  96.          ((setter cdr) block nil)    ; cut it
  97.          (opt-entry1 temp)))    ; cdr down the rest of the list
  98.       ((and (not (null (cdr block))) ; A label starts a block
  99.         (eq (caadr block) 'label))
  100.        (let* ((temp (cdr block))    ; hold the list after the cut
  101.           (current-bb (make-opt-basic-block 'first-ins temp)))
  102.          (setf (last-ins (car bblist)) (car block))
  103.          (setq bblist (cons current-bb bblist))
  104.          ((setter cdr) block nil)    ; cut it
  105.          (opt-entry1 temp)))
  106.       (t (opt-entry1 (cdr block)))))
  107.  
  108.   (defun opt-entry (block1)
  109.     (let ((current-bb (make-opt-basic-block 'first-ins block1)))
  110.       (setq bblist (cons current-bb nil))
  111.       (setq use-def-table (make-table))
  112.       (opt-entry1 block1)
  113. ;; Fix up last block - it might be null if last instruction is a null,
  114. ;; otherwise it needs to have last-ins set
  115.       (if (null (first-ins (car bblist)))
  116.       (setq bblist (cdr bblist))
  117.     (setf (last-ins (car bblist))
  118.           (car (last-pair (first-ins (car bblist))))))
  119. ;; bblist is now a reversed list of basic blocks
  120.       (setq bblist (reverse bblist))
  121. ;; set up the tempory table which joins labels to basic blocks
  122.       (setuplabeltable)
  123. ;; now fix up the pointers which link the basic blocks
  124.       (fixlinks)
  125.       (setup-def-use bblist)
  126.       (format t "~a~%" bblist)))
  127.  
  128.   (defun setup-def-use (bblist)
  129.     (if (null bblist) nil
  130.       (progn
  131.     (setup-genkill1 (car bblist))
  132.     (setup-def-use (cdr bblist)))))
  133.   
  134.   (defun setuplabeltable ()
  135.     (setq label-tab (make-table))
  136.     (add-ent bblist))
  137.  
  138.   (defun add-ent1 (x bblock)            ;x is a list of instructions
  139.     (if (eq (caar x) 'label)
  140.     ((setter table-ref) label-tab (cadar x) bblock)
  141.       nil))
  142.  
  143.   (defun add-ent (bbl)
  144.     (if (null bbl) nil
  145.       (progn
  146.     (add-ent1 (first-ins (car bbl)) (car bbl))
  147.     (add-ent (cdr bbl)))))
  148.  
  149.   (defun fixlinks ()
  150.     (fixlinks1 bblist)
  151.     (fixlinks2 bblist))
  152.  
  153.   ;; Given bblist, a list of basic blocks, we construct the list of
  154.   ;; following blocks. The first part is trivial, as we only need
  155.   ;; to add the next bblock on
  156.   (defun fixlinks1 (bbl)
  157.     (if (null bbl) nil
  158.       (let* ((ins (last-ins (car bbl)))
  159.         (endtype (table-ref endsbb-table (car ins))))        
  160.     ;; The trivial part - join to next blockf unless it is a jump
  161.     (if (or (null (cdr bbl)) (eq (car ins) 'jump)) nil
  162.       ((setter next-blk) (car bbl) (cons (cadr bbl) (next-blk (car bbl)))))
  163.     ;; The slightly less trivial bit - join to other blocks
  164.     (if (eq endtype 'ajump)
  165.         ((setter next-blk) (car bbl)
  166.           (cons (table-ref-or-bust label-tab
  167.                        (if (eq (car ins) 'jump)
  168.                            (cadr ins)
  169.                          (fourth ins)))
  170.             (next-blk (car bbl))))
  171.         nil)
  172.     (fixlinks1 (cdr bbl)))))
  173.  
  174.   ;; set up the back pointers
  175.   (defun fixlinks2 (bbl)
  176.     (if (null bbl) nil
  177.       (progn
  178.     (for (setq i (next-blk (car bbl))) (not (null i)) (setq i (cdr i))
  179.          ((setter prev-blk) (car i) (cons (car bbl) (prev-blk (car i)))))
  180.     (fixlinks2 (cdr bbl)))))
  181.  
  182.   (defun setup-def-use-table (bbl)
  183.     (if (null bbl) nil
  184.       (progn
  185.     (setup1-def-use-table (first-ins (car bbl)))
  186.     (setup-def-use-table (cdr bbl)))))
  187.  
  188.   ;; Setup the list of registers which are generated and killed
  189.   ;; by this basic block
  190.   (defun setup-genkill1 (bb)
  191.     (let ((gk (genkill (cons nil nil) (first-ins bb))))
  192.       (setf (gen bb) (car gk))
  193.       (setf (kill bb) (cdr gk))))
  194.  
  195.   ;; return a cons cell. CAR is a list of 'gen' registers, CDR is a list
  196.   ;; of 'killed' registers, insl is an instruction list
  197.   (defun genkill (res insl)
  198.     (if (null insl) res
  199.       (let ((command (caar insl))    ;Elvira Instruction
  200.         (args (cdar insl))        ;Its arguements
  201.         (genl (car res))        ;Generated definitions
  202.         (killl (cdr res)))        ;Killed definitions
  203.     (cond
  204.      ((eq command 'alloca))        ;takes a number
  205.      ((eq command 'apply)        ;o1=apply(i1,i2)
  206.       (setq killl (addmember killl (car args)))
  207.       (setq killl (addmember killl (cadr args)))
  208.       (setq genl (addmember genl 'o1)))
  209.      ((eq command 'begin-let/cc))    ;no parameters
  210.      ((eq command 'begin-unwind-protect)
  211.       (setq killl (addmember killl (car args))))
  212.      ((eq command 'begin-with-handler)
  213.       (setq killl (addmember killl (car args))))
  214.      ((eq command 'bind))        ;need to think about this one
  215.      ((eq command 'dealloca))    ;takes a number
  216.      ((eq command 'entry))        ;Should use the initial regs
  217.      ((eq command 'end-let/cc))    ;no parameters
  218.      ((eq command 'end-unwind-protect)) ;no parameters
  219.      ((eq command 'end-with-handler)) ;no parameters
  220.      ((eq command 'function))    ;module,name,num-args
  221.      ((eq command 'jump))        ;label
  222.      ((eq command 'jumpeq)        ;reg reg label. 2nd reg can be 'nil
  223.       (setq killl (addmember killl (car args)))
  224.       (setq killl (addmember killl (cadr args))))
  225.      ((eq command 'return)
  226.       (setq killl (addmember killl 'o1))) ;need to think about this one
  227.      ((eq command 'unbind))
  228.      ((eq command 'cons)
  229.       (setq killl (addmember killl (cadr args)))
  230.       (setq killl (addmember killl (caddr args)))
  231.       (setq genl (addmember genl (car args))))
  232.      ((eq command 'gctrap))        ;does not effect usage
  233.      ((eq command 'label))        ;does not effect usage
  234.      ((eq command 'link)
  235.        (cond
  236.          ((eq (car args) 'self) nil)
  237.          ((symbolp (car args)) (break))
  238.          ((eq (caar args) 'local)
  239.            (setq killl (killmultiple killl (cadr args)))
  240.            (setq genl (addmember genl 'o1)))
  241.          ((eq (caar args) 'nonlocal)
  242.            (setq killl (killmultiple killl (cadr args)))
  243.            (setq genl (addmember genl 'o1)))
  244.          ((eq (caar args) 'display))
  245.          (t (error "Unknown link" el2c-error))))
  246.      ((eq command 'load)
  247.        (setq genl (addmember genl (car args)))
  248.        (setq killl (addopand killl (cadr args))))
  249.      ((eq command 'store)
  250.        (setq killl (addmember killl (car args)))
  251.        (setq genl (addopand genl (cadr args))))
  252.      (t (format t "UNKNOWN(~a ~a);~%" command args)))
  253.     ; cdr down the list
  254.     (genkill (cons genl killl) (cdr insl))
  255.     )))
  256.   
  257.   (defun addopand (l opand)
  258.     l)
  259.  
  260.   (defun addmember (list newmem)
  261.     (if (memq newmem list) list (cons newmem list)))
  262.   
  263.   (defun killmultiple (list number)
  264.     (killmultiple1 list number '(i1 i2 i3 i4 i5 i6 i7 i8 i9)))
  265.   
  266.   (defun killmultiple1 (list number regs)
  267.     (if (zerop number) list
  268.       (killmultiple1 (addmember list (car regs)) (binary-minus number 1)
  269.              (cdr regs))))
  270.  
  271.     ;; insl is a list of instructions
  272.   (defun setup1-def-use-table (insl)
  273.     (if (null insl) nil
  274.       (progn
  275.     (setup2-def-use-table (car insl) (cdar insl))
  276.     (setup1-def-use-table (cdr insl)))))
  277.  
  278.   (defun setup2-def-use-table (ins opands)
  279.     (if (null opands) nil
  280.       (progn
  281.     (if (atom (car opands))
  282.         ((setter table-ref) use-def-table (car opands)
  283.          (cons ins (table-ref use-def-table (car opands))))
  284.       (error (format nil "!Atom in setup2-def-use-table ~a~%" elopt-error)))
  285.     (setup2-def-use-table ins (cdr opands)))))
  286.   
  287.   (defun init-bbs-table ()
  288.     ((setter table-ref) endsbb-table 'jump 'ajump)
  289.     ((setter table-ref) endsbb-table 'jumpeq 'ajump)
  290.     ((setter table-ref) endsbb-table 'jumpne 'ajump)
  291.     ((setter table-ref) endsbb-table 'jumpgt 'ajump)
  292.     ((setter table-ref) endsbb-table 'jumpgeq 'ajump)
  293.     ((setter table-ref) endsbb-table 'jumple 'ajump)
  294.     ((setter table-ref) endsbb-table 'jumpleq 'ajump)
  295.     ((setter table-ref) endsbb-table 'entry t)
  296.     )
  297.  
  298.   (init-bbs-table)
  299.   (setq fred '((entry fred)
  300.            (load o1 1)
  301.            (label 5)
  302.            (store o1 (display 1 2))
  303.            (jumpeq l1 nil 6)
  304.            (cons l1 i1 i2)
  305.            (load o1 4)
  306.            (label 6)
  307.            ))
  308.   (defun try-it ()
  309.     (opt-entry (copy fred)))
  310.   
  311.   (export optimise opt-code-stream)
  312. )
  313.